// Copyright (c) 2012-2013, yuno. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
package sugarmintcandy.widgetwindow;

import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity implements
	AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener,
	SharedPreferences.OnSharedPreferenceChangeListener {
    private MainApplication mApplication;
    private MainDatabase mDatabase;
    private MyAppWidgetHostManager mHostManager;
    private SharedPreferences mPreferences;
    private int mAddingAppWidgetId;
    private int mCurrentWorkspace;
    private long mSelectedItemId;

    private ListView mListView;
    private WindowInfoListAdapter mAdapter;
    private ContentObserver mContentObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);

	mApplication = (MainApplication) getApplication();
	mDatabase = mApplication.getDatabase();
	mHostManager = mApplication.getHostManager();
	mPreferences = PreferenceManager.getDefaultSharedPreferences(this);

	setContentView(R.layout.main);
	mListView = (ListView) findViewById(R.id.list_view);
	mListView.setEmptyView(findViewById(R.id.empty_view));
	mAdapter = new WindowInfoListAdapter(mDatabase);
	mListView.setAdapter(mAdapter);
	mListView.setOnItemClickListener(this);
	mListView.setOnItemLongClickListener(this);
	registerForContextMenu(mListView);

	mContentObserver = new MyContentObserver(new Handler());
	mDatabase.registerObserver(mContentObserver);
	mPreferences.registerOnSharedPreferenceChangeListener(this);
	fetchPreferences();
    }

    @Override
    protected void onDestroy() {
	super.onDestroy();
	mDatabase.unregisterObserver(mContentObserver);
	mPreferences.unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
	super.onRestoreInstanceState(savedInstanceState);
	mAddingAppWidgetId = savedInstanceState.getInt("mAddingAppWidgetId");
	mSelectedItemId = savedInstanceState.getLong("mSelectedItemId");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);
	outState.putInt("mAddingAppWidgetId", mAddingAppWidgetId);
	outState.putLong("mSelectedItemId", mSelectedItemId);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
	super.onCreateOptionsMenu(menu);
	getMenuInflater().inflate(R.menu.main, menu);
	return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
	super.onPrepareOptionsMenu(menu);
	switch (mCurrentWorkspace) {
	case 1:
	    menu.findItem(R.id.workspace_1).setChecked(true);
	    break;
	case 2:
	    menu.findItem(R.id.workspace_2).setChecked(true);
	    break;
	case 3:
	    menu.findItem(R.id.workspace_3).setChecked(true);
	    break;
	case 4:
	    menu.findItem(R.id.workspace_4).setChecked(true);
	    break;
	case 5:
	    menu.findItem(R.id.workspace_5).setChecked(true);
	    break;
	case 6:
	    menu.findItem(R.id.workspace_6).setChecked(true);
	    break;
	case 7:
	    menu.findItem(R.id.workspace_7).setChecked(true);
	    break;
	case 8:
	    menu.findItem(R.id.workspace_8).setChecked(true);
	    break;
	case 9:
	    menu.findItem(R.id.workspace_9).setChecked(true);
	    break;
	case 10:
	    menu.findItem(R.id.workspace_10).setChecked(true);
	    break;
	}
	return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
	int id = item.getItemId();
	if (id == R.id.new_window) {
	    doNewWindow();
	    return true;
	}
	if (id == R.id.settings) {
	    startActivity(new Intent(this, SettingsActivity.class));
	    return true;
	}
	if (id == R.id.help) {
	    startActivity(new Intent(this, HelpActivity.class));
	    return true;
	}
	if (id == R.id.workspace_1) {
	    switchWorkspace(1);
	    return true;
	}
	if (id == R.id.workspace_2) {
	    switchWorkspace(2);
	    return true;
	}
	if (id == R.id.workspace_3) {
	    switchWorkspace(3);
	    return true;
	}
	if (id == R.id.workspace_4) {
	    switchWorkspace(4);
	    return true;
	}
	if (id == R.id.workspace_5) {
	    switchWorkspace(5);
	    return true;
	}
	if (id == R.id.workspace_6) {
	    switchWorkspace(6);
	    return true;
	}
	if (id == R.id.workspace_7) {
	    switchWorkspace(7);
	    return true;
	}
	if (id == R.id.workspace_8) {
	    switchWorkspace(8);
	    return true;
	}
	if (id == R.id.workspace_9) {
	    switchWorkspace(9);
	    return true;
	}
	if (id == R.id.workspace_10) {
	    switchWorkspace(10);
	    return true;
	}
	return super.onOptionsItemSelected(item);
    }

    private void switchWorkspace(int workspace) {
	SharedPreferences.Editor editor = mPreferences.edit();
	editor.putInt(PreferenceKeys.CURRENT_WORKSPACE, workspace);
	editor.commit();
    }

    @Deprecated
    @Override
    protected Dialog onCreateDialog(int id) {
	if (id == R.id.window_color) {
	    final ColorPicker colorPicker = new ColorPicker(this);
	    colorPicker.setId(R.id.color_picker);
	    AlertDialog.Builder b = new AlertDialog.Builder(this);
	    b.setTitle(R.string.window_color);
	    b.setView(colorPicker);
	    b.setPositiveButton(android.R.string.ok,
		    new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
			    doChangeBackgroundColor(colorPicker.getColor());
			}
		    });
	    b.setNegativeButton(android.R.string.cancel, null);
	    return b.create();
	}
	if (id == R.id.title_bar_color) {
	    final ColorPicker colorPicker = new ColorPicker(this);
	    colorPicker.setId(R.id.color_picker);
	    AlertDialog.Builder b = new AlertDialog.Builder(this);
	    b.setTitle(R.string.title_bar_color);
	    b.setView(colorPicker);
	    b.setPositiveButton(android.R.string.ok,
		    new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
			    doChangeTitleBarColor(colorPicker.getColor());
			}
		    });
	    b.setNegativeButton(android.R.string.cancel, null);
	    return b.create();
	}
	if (id == R.id.title_bar_text) {
	    final EditText text = (EditText) getLayoutInflater().inflate(
		    R.layout.title_text, null, false);
	    text.setOnEditorActionListener(new TextView.OnEditorActionListener() {
		@Override
		public boolean onEditorAction(TextView v, int actionId,
			KeyEvent event) {
		    if (actionId == EditorInfo.IME_ACTION_DONE) {
			dismissDialog(R.id.title_bar_text);
			doChangeTitleText(text.getText().toString());
			return true;
		    }
		    return false;
		}
	    });
	    AlertDialog.Builder b = new AlertDialog.Builder(this);
	    b.setTitle(R.string.title_bar_text);
	    b.setView(text);
	    b.setPositiveButton(android.R.string.ok,
		    new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
			    doChangeTitleText(text.getText().toString());
			}
		    });
	    b.setNegativeButton(android.R.string.cancel, null);
	    return b.create();
	}
	if (id == R.id.configure_error) {
	    AlertDialog.Builder b = new AlertDialog.Builder(this);
	    b.setIcon(android.R.drawable.ic_dialog_alert);
	    b.setTitle(R.string.error_title);
	    b.setMessage(R.string.configure_error);
	    b.setPositiveButton(android.R.string.ok, null);
	    return b.create();
	}
	return super.onCreateDialog(id);
    }

    @Deprecated
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
	super.onPrepareDialog(id, dialog);
	if (id == R.id.title_bar_text) {
	    WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	    if (info != null) {
		EditText editText = (EditText) dialog
			.findViewById(android.R.id.text1);
		editText.setText(info.getTitleBarText());
	    }
	}
	if (id == R.id.title_bar_color) {
	    WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	    if (info != null) {
		ColorPicker colorPicker = (ColorPicker) dialog
			.findViewById(R.id.color_picker);
		colorPicker.prepare();
		colorPicker.setColor(info.titleBarColor);
	    }
	}
	if (id == R.id.window_color) {
	    WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	    if (info != null) {
		ColorPicker colorPicker = (ColorPicker) dialog
			.findViewById(R.id.color_picker);
		colorPicker.prepare();
		colorPicker.setColor(info.windowColor);
	    }
	}
    }

    private void doNewWindow() {
	mAddingAppWidgetId = mHostManager.allocateAppWidgetId();
	Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
	intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAddingAppWidgetId);
	intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.new_window));
	intent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO,
		new ArrayList<Parcelable>());
	intent.putParcelableArrayListExtra(
		AppWidgetManager.EXTRA_CUSTOM_EXTRAS, new ArrayList<Bundle>());
	startActivityForResult(intent, R.id.app_widget_pick);
    }

    private void doNewWindow(int appWidgetId) {
	WindowInfo info = new WindowInfo();
	info.init(mDatabase, appWidgetId);
	mDatabase.addWindowInfo(info);
    }

    private boolean doConfigureWidget(int appWidgetId,
	    AppWidgetProviderInfo info) {
	Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
	intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
	intent.setComponent(info.configure);
	startActivityForResult(intent, R.id.app_widget_configure);
	return true;
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);
	if (requestCode == R.id.app_widget_pick && mAddingAppWidgetId != 0) {
	    int appWidgetId = mAddingAppWidgetId;
	    AppWidgetProviderInfo info = AppWidgetManager.getInstance(this)
		    .getAppWidgetInfo(appWidgetId);
	    if (resultCode == RESULT_OK && info != null) {
		if (info.configure != null) {
		    try {
			doConfigureWidget(appWidgetId, info);
		    } catch (RuntimeException ex) {
			mHostManager.deleteAppWidgetId(appWidgetId);
			mAddingAppWidgetId = 0;
			showDialog(R.id.configure_error);
		    }
		} else {
		    doNewWindow(appWidgetId);
		    mAddingAppWidgetId = 0;
		}
	    } else {
		mHostManager.deleteAppWidgetId(appWidgetId);
		mAddingAppWidgetId = 0;
	    }
	}
	if (requestCode == R.id.app_widget_configure && mAddingAppWidgetId != 0) {
	    int appWidgetId = mAddingAppWidgetId;
	    if (resultCode == RESULT_OK) {
		doNewWindow(appWidgetId);
		mAddingAppWidgetId = 0;
	    } else {
		mHostManager.deleteAppWidgetId(appWidgetId);
		mAddingAppWidgetId = 0;
	    }
	}
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
	    long id) {
	mSelectedItemId = id;
	openContextMenu(mListView);
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view,
	    int position, long id) {
	mSelectedItemId = id;
	openContextMenu(mListView);
	return true;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
	    ContextMenuInfo menuInfo) {
	super.onCreateContextMenu(menu, v, menuInfo);
	if (v == mListView) {
	    getMenuInflater().inflate(R.menu.window_list_item, menu);
	    if (mAdapter.getCount() <= 1
		    || mAdapter.findItemById(mSelectedItemId) == mAdapter
			    .getItem(0)) {
		menu.findItem(R.id.bring_to_front).setVisible(false);
	    }
	    WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	    if (info != null) {
		if ((info.workspace & (1 << mCurrentWorkspace)) != 0) {
		    menu.findItem(R.id.show_window).setVisible(false);
		} else {
		    menu.findItem(R.id.hide_window).setVisible(false);
		}
	    }
	}
    }

    @SuppressWarnings("deprecation")
    @Override
    public boolean onContextItemSelected(MenuItem item) {
	int itemId = item.getItemId();
	if (itemId == R.id.title_bar_text) {
	    showDialog(R.id.title_bar_text);
	    return true;
	} else if (itemId == R.id.title_bar_color) {
	    showDialog(R.id.title_bar_color);
	    return true;
	} else if (itemId == R.id.window_color) {
	    showDialog(R.id.window_color);
	    return true;
	} else if (itemId == R.id.reset_position) {
	    doResetPosition();
	    return true;
	} else if (itemId == R.id.bring_to_front) {
	    doBringToFront();
	    return true;
	} else if (itemId == R.id.show_window) {
	    doShowWindow();
	    return true;
	} else if (itemId == R.id.hide_window) {
	    doHideWindow();
	    return true;
	} else if (itemId == R.id.delete_window) {
	    doDeleteWindow();
	    return true;
	} else {
	    return super.onContextItemSelected(item);
	}
    }

    private void doResetPosition() {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.fetchWindowInfo(info);
	    info.resetPosition(mDatabase);
	    mDatabase.updateWindowInfo(info, true);
	}
    }

    private void doBringToFront() {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.fetchWindowInfo(info);
	    info.zOrder = mDatabase.getMaxZOrder() + 1;
	    mDatabase.updateWindowInfo(info, true);
	}
    }

    private void doShowWindow() {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.fetchWindowInfo(info);
	    info.workspace |= 1 << mCurrentWorkspace;
	    mDatabase.updateWindowInfo(info, true);
	}
    }

    private void doHideWindow() {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.fetchWindowInfo(info);
	    info.workspace &= ~(1 << mCurrentWorkspace);
	    mDatabase.updateWindowInfo(info, true);
	}
    }

    private void doDeleteWindow() {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.deleteWindowInfo(info);
	}
	mHostManager.deleteAppWidgetId(info.appWidgetId);
    }

    private void doChangeBackgroundColor(int color) {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.fetchWindowInfo(info);
	    info.windowColor = color;
	    mDatabase.updateWindowInfo(info, true);
	}
	mDatabase.addRecentColor(color);
    }

    private void doChangeTitleBarColor(int color) {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.fetchWindowInfo(info);
	    info.titleBarColor = color;
	    mDatabase.updateWindowInfo(info, true);
	}
	mDatabase.addRecentColor(color);
    }

    private void doChangeTitleText(String text) {
	WindowInfo info = mAdapter.findItemById(mSelectedItemId);
	if (info != null) {
	    mDatabase.fetchWindowInfo(info);
	    info.titleBarText = text;
	    mDatabase.updateWindowInfo(info, true);
	}
    }

    private class MyContentObserver extends ContentObserver {
	public MyContentObserver(Handler handler) {
	    super(handler);
	}

	@SuppressWarnings("deprecation")
	@Override
	public void onChange(boolean selfChange) {
	    mAdapter.refresh();
	    if (mAdapter.findItemById(mSelectedItemId) == null) {
		removeDialog(R.id.title_bar_color);
		removeDialog(R.id.window_color);
		closeContextMenu();
	    }
	}
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
	    String key) {
	if (PreferenceKeys.CURRENT_WORKSPACE.equals(key)) {
	    fetchPreferences();
	    mAdapter.refresh();
	}
    }

    private void fetchPreferences() {
	mCurrentWorkspace = mPreferences.getInt(
		PreferenceKeys.CURRENT_WORKSPACE, 0);
    }
}
